﻿using System.Linq;
using SPDbFileExtractor.Framework.Code;
using SPDbFileExtractor.Framework.Entities;
using SPDbFileExtractor.Properties;
using System;
using System.Collections.Generic;
using System.Windows.Forms;


namespace SPDbFileExtractor.Forms
{
    public sealed partial class Main : Form
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Main" /> class.
        /// </summary>
        public Main()
        {
            InitializeComponent();

            Init();
        }

        /// <summary>
        /// Init me.
        /// </summary>
        /// <exception cref="System.NotImplementedException"></exception>
        private void Init()
        {
            try
            {
                LoadConnections();
            }
            catch (Exception ex)
            {
                Utils.ShowWinFormError("Error while loading connections: " + ex.Message);
            }
        }

        /// <summary>
        /// Loads saved connections and binds the combo.
        /// </summary>
        private void LoadConnections()
        {
            comboConnections.Items.Clear();

            var validConnections =
                Settings.Default.savedConnStrings.ToArray().ToList().Where(
                    i => i != null && i.ToString().Trim().Length > 0).ToList();

            comboConnections.Items.AddRange(validConnections.ToArray());

            var matchedItem = comboConnections.FindString(ConnectionManager.ConnectionString);
            comboConnections.SelectedIndex = matchedItem;
        }

        /// <summary>
        /// Handles the Click event of the btnBrowseConn control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void btnBrowseConn_Click(object sender, EventArgs e)
        {
            BrowseForConnection();
        }

        /// <summary>
        /// Browses for connection.
        /// </summary>
        private void BrowseForConnection()
        {
            ConnectionManager.SetupConnection();

            foreach (var conn in Settings.Default.savedConnStrings)
            {
                if (conn != null)
                {
                    if (string.Equals(conn.ToString(), ConnectionManager.ConnectionString, StringComparison.OrdinalIgnoreCase))
                    {
                        comboConnections.SelectedText = ConnectionManager.ConnectionString;
                        var matchedItem = comboConnections.FindString(ConnectionManager.ConnectionString);
                        comboConnections.SelectedIndex = matchedItem;

                        return;
                    }
                }
            }

            Settings.Default.savedConnStrings.Add(ConnectionManager.ConnectionString);
            Settings.Default.Save();

            LoadConnections();
        }

        /// <summary>
        /// Binds the sites.
        /// </summary>
        private void BindSites()
        {
            if (!ConnectionManager.ConnectionValid)
            {
                return;
            }

            try
            {
                var sites = ContentDbManager.GetSites(comboConnections.SelectedItem.ToString());

                if (sites.Count == 0)
                {
                    Utils.ShowMessage("No sites were found in the selected content database.");
                    return;
                }

                comboSites.DataSource = sites;
                comboSites.Refresh();
            }
            catch (Exception ex)
            {
                Utils.ShowWinFormError("Error while binding sites: " + ex.Message);
            }
        }

        /// <summary>
        /// Binds the webs.
        /// </summary>
        private void BindWebs()
        {
            if (!ConnectionManager.ConnectionValid)
            {
                return;
            }

            if (comboSites.SelectedItem == null)
            {
                return;
            }

            try
            {
                var webs = ContentDbManager.GetWebs(comboConnections.SelectedItem.ToString(), ((Site)comboSites.SelectedItem).SiteId);

                if (webs.Count == 0)
                {
                    Utils.ShowMessage("No webs were found in the selected content database.");
                    return;
                }

                comboWebs.DataSource = webs;
                comboWebs.Refresh();
            }
            catch (Exception ex)
            {
                Utils.ShowWinFormError("Error while binding webs: " + ex.Message);
            }
        }

        /// <summary>
        /// Binds the lists.
        /// </summary>
        private void BindLists()
        {
            if (!ConnectionManager.ConnectionValid)
            {
                return;
            }

            if (comboSites.SelectedItem == null)
            {
                return;
            }

            if (comboWebs.SelectedItem == null)
            {
                return;
            }

            try
            {
                var lists = ContentDbManager.GetLists(comboConnections.SelectedItem.ToString(), ((Web)comboWebs.SelectedItem).WebId);

                if (lists.Count == 0)
                {
                    Utils.ShowMessage("No lists were found in the selected content database.");
                    return;
                }

                comboLists.DataSource = lists;
                comboLists.Refresh();
            }
            catch (Exception ex)
            {
                Utils.ShowWinFormError("Error while binding lists: " + ex.Message);
            }
        }

        /// <summary>
        /// Handles the DropDown event of the comboSites control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void comboSites_DropDown(object sender, EventArgs e)
        {
            ResetAllSelections();

            BindSites();
        }

        /// <summary>
        /// Handles the DropDown event of the comboWebs control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void comboWebs_DropDown(object sender, EventArgs e)
        {
            ResetWebSelection();
            ResetListSelection();
            ResetListItemSelection();
            ResetListItemVersionSelection();

            BindWebs();
        }

        /// <summary>
        /// Handles the DropDown event of the comboLists control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void comboLists_DropDown(object sender, EventArgs e)
        {
            ResetListSelection();
            ResetListItemSelection();
            ResetListItemVersionSelection();

            BindLists();
        }

        /// <summary>
        /// Resets all selections.
        /// </summary>
        private void ResetAllSelections()
        {
            ResetSiteSelection();
            ResetWebSelection();
            ResetListSelection();
            ResetListItemSelection();
            ResetListItemVersionSelection();
        }

        /// <summary>
        /// Resets the site selection.
        /// </summary>
        private void ResetSiteSelection()
        {
            comboSites.ResetBindings();
            comboSites.DataSource = new List<object>();
        }

        /// <summary>
        /// Resets the web selection.
        /// </summary>
        private void ResetWebSelection()
        {
            comboWebs.ResetBindings();
            comboWebs.DataSource = new List<object>();

        }

        /// <summary>
        /// Resets the list selection.
        /// </summary>
        private void ResetListSelection()
        {
            comboLists.ResetBindings();
            comboLists.DataSource = new List<object>();
        }

        /// <summary>
        /// Resets the list item selection.
        /// </summary>
        private void ResetListItemSelection()
        {
            comboItems.ResetBindings();
            comboItems.DataSource = new List<object>();
        }

        /// <summary>
        /// Resets the list item version selection.
        /// </summary>
        private void ResetListItemVersionSelection()
        {
            gvVersions.Rows.Clear();
        }

        /// <summary>
        /// Binds the items.
        /// </summary>
        private void BindItems()
        {
            if (!ConnectionManager.ConnectionValid)
            {
                return;
            }

            if (comboSites.SelectedItem == null)
            {
                return;
            }

            if (comboWebs.SelectedItem == null)
            {
                return;
            }

            if (comboLists.SelectedItem == null)
            {
                return;
            }

            try
            {
                var items = ContentDbManager.GetItems(comboConnections.SelectedItem.ToString(),
                                                                                ((List)comboLists.SelectedItem).ListId,
                                                                                tbItemFilter.Text, tbDirFilter.Text);

                if (items.Count == 0)
                {
                    Utils.ShowMessage("No items were found in the selected content database.");
                    return;
                }

                items.Insert(0, new ListItem());
                comboItems.DataSource = items;
                comboItems.Refresh();
            }
            catch (Exception ex)
            {
                Utils.ShowWinFormError("Error while binding items: " + ex.Message);
            }
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the comboItems control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void comboItems_SelectedIndexChanged(object sender, EventArgs e)
        {
            BindItemVersions();
        }

        /// <summary>
        /// Binds the item versions.
        /// </summary>
        private void BindItemVersions()
        {
            if (!ConnectionManager.ConnectionValid)
            {
                return;
            }

            if (comboSites.SelectedItem == null)
            {
                return;
            }

            if (comboWebs.SelectedItem == null)
            {
                return;
            }

            if (comboLists.SelectedItem == null)
            {
                return;
            }

            if (comboItems.SelectedItem == null || comboItems.SelectedItem.ToString().Length == 0)
            {
                gvVersions.Rows.Clear();
                return;
            }

            try
            {
                gvVersions.Rows.Clear();

                var versions = ContentDbManager.GetItemVersions(comboConnections.SelectedItem.ToString(),
                                                                ((ListItem)comboItems.SelectedItem).FileId);

                if (versions.Count == 0)
                {
                    Utils.ShowMessage("No versions were found in the selected content database.");
                    return;
                }

                foreach (FileVersion ver in versions)
                {
                    var newRowIndex = gvVersions.Rows.Add();
                    var newRow = gvVersions.Rows[newRowIndex];
                    newRow.Cells["versionNumber"].Value = ver.ETagVersion;
                    newRow.Cells["created"].Value = ver.Created;
                    newRow.Cells["author"].Value = ver.CreatedBy;
                    newRow.Cells["size"].Value = ver.Size;
                    newRow.Cells["download"].Value = "Save as...";
                    newRow.Cells["internalVersion"].Value = ver.InternalVersion;
                    newRow.Cells["fileId"].Value = ver.FileId;
                }
            }
            catch (Exception ex)
            {
                Utils.ShowWinFormError("Error while binding versions: " + ex.Message);
            }
        }

        /// <summary>
        /// Handles the CellContentClick event of the gvVersions control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="DataGridViewCellEventArgs" /> instance containing the event data.</param>
        private void gvVersions_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 6)
            {
                try
                {
                    var rowIndex = e.RowIndex;
                    var row = gvVersions.Rows[rowIndex];

                    var itemId = row.Cells["fileId"].Value;
                    var version = row.Cells["internalVersion"].Value;

                    Utils.SaveRequestedFile(new Guid(itemId.ToString()), (int)version, comboConnections.SelectedItem.ToString(), ((ListItem)comboItems.SelectedItem).FileName);
                }
                catch (Exception ex)
                {
                    Utils.ShowWinFormError("Error while saving the file: " + ex.Message);
                }
            }
        }

        /// <summary>
        /// Handles the Click event of the btnLoadItems control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void btnLoadItems_Click(object sender, EventArgs e)
        {
            ResetListItemSelection();
            ResetListItemVersionSelection();

            BindItems();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the comboConnections control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void comboConnections_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboConnections.SelectedItem == null || comboConnections.SelectedItem.ToString().Length == 0)
            {
                return;
            }

            ResetAllSelections();

            var selectedConnString = comboConnections.SelectedItem.ToString();

            var isValid = Utils.ValidateConnectionString(selectedConnString);

            if (!isValid)
            {
                Utils.ShowMessage("Selected connection string is not valid or DB (server) is currently not available.");
                return;
            }

            var dbVersionValid = ContentDbManager.VerifyDbVersion(selectedConnString);

            if (!dbVersionValid)
            {
                Utils.ShowWinFormError("Selected DB is not content DB or is incorrect version.");
            }
        }

        /// <summary>
        /// Handles the Click event of the btnDeleteConnection control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        private void btnDeleteConnection_Click(object sender, EventArgs e)
        {
            if (comboConnections.SelectedItem == null)
            {
                return;
            }

            var selectedConnection = comboConnections.SelectedItem.ToString();

            if (MessageBox.Show(@"Remove selected connection?" + Environment.NewLine + Environment.NewLine + selectedConnection, @"Connection", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Settings.Default.savedConnStrings.Remove(selectedConnection);
                Settings.Default.Save();

                LoadConnections();
            }
        }
    }
}
